package com.relytosoft.mizar.media.camera.services.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import com.relytosoft.dubhe.common.api.entity.system.SysFile;
import com.relytosoft.dubhe.common.api.service.RemoteFileService;
import com.relytosoft.mizar.media.camera.api.entity.DownLoadLog;
import com.relytosoft.mizar.media.camera.api.entity.Multimedia;
import com.relytosoft.mizar.media.camera.api.pojo.dto.VideoRecordDto;
import com.relytosoft.mizar.media.camera.services.service.DownLoadLogService;
import com.relytosoft.mizar.media.camera.services.service.StreamService;
import com.relytosoft.mizar.media.common.constant.SymbolConstants;
import com.relytosoft.mizar.media.common.enums.DownLoadStateEnum;
import com.relytosoft.mizar.media.common.enums.UpLoadFileEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author wss
 * @version 1.0
 * @date 2022/6/16 10:17
 */
@Service
public class OffLineStreamServiceImpl implements StreamService {

    static ThreadPoolExecutor threadPoolExecutor;

    static {
        threadPoolExecutor = new ThreadPoolExecutor(
                (int) (Runtime.getRuntime().availableProcessors() * 1.5),
                Runtime.getRuntime().availableProcessors() * 3,
                60L,
                TimeUnit.SECONDS,
                //选用无界的阻塞队列 则设置的mumPoolSize参数没有意义
                new LinkedBlockingDeque<Runnable>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    @Autowired
    private RemoteFileService remoteFileService;
    @Autowired
    private MultimediaServiceImpl multimediaService;
    @Autowired
    private DownLoadLogService downLoadLogService;

    @Override
    public Integer frontOperate(VideoRecordDto videoRecordDto) {
        DownLoadLog downLoadLog = VideoRecordDto.buildObject(videoRecordDto);
        downLoadLogService.save(downLoadLog);
        Integer taskId = downLoadLog.getId();
        String outputFile = OUTPUT_PATH + videoRecordDto.getDeviceId() + SymbolConstants.MINUS + RandomUtil.randomString(6) + ".avi";
        videoRecordDto.setFilePath(outputFile);
        videoRecordDto.setTaskId(taskId);
        return taskId;
    }

    @Override
    public void postOperate(VideoRecordDto videoRecordDto) {
        String filePath = videoRecordDto.getFilePath();
        BufferedInputStream inputStream = FileUtil.getInputStream(filePath);
        if (Objects.isNull(inputStream)) {
            return;
        }
        byte[] bytes = IoUtil.readBytes(inputStream);
        SysFile sysFile = remoteFileService.upload(null, FileUtil.getName(filePath), null, bytes, UpLoadFileEnum.VIDEO.getCode());
        String url = sysFile.getUrl();

        DownLoadLog downLoadLog = new DownLoadLog();
        downLoadLog.setId(videoRecordDto.getTaskId());
        downLoadLog.setState(DownLoadStateEnum.DOWNLOADING.getValue());
        downLoadLog.setResourceUrl(url);
        downLoadLog.setFileSize(String.valueOf(FileUtil.size(FileUtil.file(filePath))));
        downLoadLogService.updateById(downLoadLog);

        multimediaService.save(Multimedia.buildVideoObject(url, videoRecordDto));
        FileUtil.del(filePath);
    }

    @Override
    public Boolean abortOperate(VideoRecordDto videoRecordDto) {
        Long startTime = videoRecordDto.getStartTime();
        Long duration = videoRecordDto.getDuration();
        return DateUtil.currentSeconds() - startTime > duration;
    }
}
